package org.angelica.common.filter;

import com.google.common.collect.Lists;
import org.angelica.common.AppConstant;
import org.angelica.core.common.Constant;
import org.angelica.core.response.ResponseResult;
import org.angelica.enums.RedisKeyEnum;
import org.angelica.enums.ResponseErrorEnum;
import org.angelica.exception.ServiceErrorEnum;
import org.angelica.utils.common.JwtTokenUtil;
import org.angelica.utils.common.ToolUtil;
import org.angelica.utils.redis.RedisUtil;
import org.apache.commons.lang3.StringUtils;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * jwt token 过滤器
 * @author aizhimin
 *
 */
public class JwtTokenFilter implements Filter {

    /**
     * 不登录不需要token，但是登录之后需要token的url
     */
    private List<Pattern> excludeNoLoginUris = Lists.newArrayList();

    @Override
    public void init(FilterConfig filterConfig) {
        //不需要登录的接口
        excludeNoLoginUris.addAll(FilterHelper.excludeNoLoginApi());
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest hsRequest = (HttpServletRequest)request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        //如果不是API接口请求,则不需要登录
        if(!FilterHelper.isApiRequest(hsRequest.getRequestURI())) {
            chain.doFilter(request, response);
            return;
        }

        //如果授权信息不为空，则解析用户授权信息
        String authorization = hsRequest.getHeader(Constant.HEADER_AUTH);
        if(StringUtils.isNotBlank(authorization)){
            Long userId = JwtTokenUtil.getUserIdFromToken(AppConstant.JWT_SECRET,authorization);
            if(userId != null){
                //判断用户是否被禁用
                String forbidUserKey = RedisKeyEnum.FORBIDDEN_USER.getPrefix() + String.valueOf(userId);
                if(RedisUtil.hasKey(forbidUserKey)){
                    ToolUtil.responseError(httpResponse, ResponseResult.error(ServiceErrorEnum.USER_FORBIDDEN.getCode(),ServiceErrorEnum.USER_FORBIDDEN.getMsg()));
                    return;
                }
                request.setAttribute(Constant.CURRENT_USER_ID,userId);
                chain.doFilter(request, response);
                return;
            }else{
                ToolUtil.responseError(httpResponse, ResponseResult.error(ResponseErrorEnum.TOKEN_INVALID));
            }
        }else{
            //判断是否为免登录请求
            if(isExcludeNoLoginUri(hsRequest.getRequestURI())){
                chain.doFilter(request, response);
                return;
            }else{
                //其他情况则授权失败
                ToolUtil.responseError(httpResponse, ResponseResult.error(ResponseErrorEnum.TOKEN_INVALID));
            }
        }
    }

    @Override
    public void destroy() {

    }

    /**
     * 判断是否是免登陆的URI
     * @param requestUri
     * @return
     */
    private boolean isExcludeNoLoginUri(String requestUri) {
        for (Pattern pattern : excludeNoLoginUris) {
            Matcher matcher = pattern.matcher(requestUri);
            if (matcher.matches()) {
                return true;
            }
        }
        return false;
    }

}
